package com.miage.itrading.server.dao;

import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.miage.itrading.server.utils.ConnecteurBDD;
import com.miage.itrading.shared.Const;
import com.miage.itrading.shared.Util;
import com.miage.itrading.shared.entites.Cotation;
import com.miage.itrading.shared.entites.Historique;
import com.miage.itrading.shared.entites.Intraday;

public class CotationDAO {
	private final Cotation	cotation;

	public CotationDAO() {
		this.cotation = new Cotation();
	}

	public CotationDAO(Cotation cot) {
		this.cotation = cot;
		System.out.println("cotation " + cotation.getHistoriques().size());
		System.out.println("cot " + cot.getHistoriques().size());
	}

	public CotationDAO(String nom, String mnemonique) throws IOException {
		this.cotation = new Cotation();
		cotation.setNom(nom);
		cotation.setMnemonique(mnemonique);

	}

	@SuppressWarnings("deprecation")
	public void ajouterHistorique(String date, String ouverture,
			String fermeture, String plusBas, String plusHaut, String volume) {
		Historique h = new Historique();

		h.setDate(new Timestamp((Integer.parseInt(date.split("-")[0])) - 1900,
				Integer.parseInt(date.split("-")[1]) - 1, Integer.parseInt(date
						.split("-")[2]) - 1, 17, 35, 0, 0));
		h.setOuverture(Float.parseFloat(ouverture));
		h.setFermeture(Float.parseFloat(fermeture));
		h.setPlusBas(Float.parseFloat(plusBas));
		h.setPlusHaut(Float.parseFloat(plusHaut));
		h.setVolume(Float.parseFloat(volume));

		cotation.getHistoriques().add(h);
	}

	public Historique donneeTableau(int i) {
		Historique retour = null;
		if (cotation.getHistoriques().get(i) != null) {
			retour = cotation.getHistoriques().get(i);
		}

		return retour;
	}

	public void ecrireCotation() throws SQLException {

		if (getCotationByName(cotation.getNom(), false) != null) {

			// Vérifie l'existence de la cotation avant l'insertion
			ResultSet result = ConnecteurBDD.executeQuery(
					"SELECT idcotation FROM cotation WHERE nom = '"
							+ cotation.getNom() + "' AND mnemonique = '"
							+ cotation.getMnemonique() + "'");

			if (!result.next()) {
				ConnecteurBDD.executeUpdate(
						"INSERT INTO cotation (nom, mnemonique) VALUES ('"
								+ cotation.getNom() + "', '"
								+ cotation.getMnemonique() + "')");
			}

			result.close();
		}

		Cotation transcient = new Cotation();
		transcient = getCotationByName(cotation.getNom(), false);

		final String SQLinsert = "INSERT INTO historique (idcotation, date, ouverture, fermeture, plusbas, plushaut, volume) VALUES ";
		String SQLvalues;

		/**
		 * Insère les enregistrements par lots de 1000 pour accélérer le
		 * traitement
		 */

		Historique h;
		int nbEnregistrements = cotation.getHistoriques().size();

		for (int i = 0; i < nbEnregistrements; ++i) {

			SQLvalues = "";
			while (((i % Const.NB_ENREGISTREMENTS_GROUPE != 0) || (i == 0))
					&& (i < nbEnregistrements)) {
				h = cotation.getHistoriques().get(i);

				SQLvalues += "(" + transcient.getIdCotation() + ",'"
						+ h.getDate() + "'," + h.getOuverture() + ","
						+ h.getFermeture() + "," + h.getPlusBas() + ","
						+ h.getPlusHaut() + "," + h.getVolume() + "),";

				++i;
			}

			// Retire la derniere ","
			SQLvalues = SQLvalues.substring(0, SQLvalues.length() - 1);

			GWT.log(SQLinsert + SQLvalues);

			ConnecteurBDD.executeUpdate(
					SQLinsert + SQLvalues);
		}
	}

	/**
	 * 
	 * @param indice
	 *            id de l'indice
	 * @return valeurs qui composent l'indice, triées par nom asc
	 * @throws SQLException
	 */
	public List<Integer> getCompositionIndice(int indice) throws SQLException {
		ResultSet result = ConnecteurBDD.executeQuery(
						"SELECT i.idcotation FROM indice i, cotation c WHERE i.idindice = "
								+ indice
								+ " AND i.idcotation = c.idcotation ORDER BY c.nom ASC");

		ArrayList<Integer> composition = new ArrayList<Integer>();
		while (result.next()) {
			composition.add(result.getInt("IdIndice"));
		}

		return composition;
	}

	public Cotation getCotation() {
		return cotation;

	}

	/**
	 * Fonction commune à tous les getCotationBy
	 * 
	 * @param rs
	 * @param bdd
	 * @return
	 * @throws SQLException
	 */
	private Cotation getCotation(ResultSet rs, boolean getAllHistorique) throws SQLException {

		Cotation c = new Cotation();

		if (rs.next()) {
			c.setIdCotation(rs.getInt("idcotation"));
			c.setMnemonique(rs.getString("mnemonique"));
			c.setNom(rs.getString("nom"));

			String sqlOrder;
			if (getAllHistorique) {
				sqlOrder = "SELECT * FROM historique WHERE (idcotation = "
						+ c.getIdCotation() + ") ORDER BY date ASC";
			} else {
				sqlOrder = "SELECT * FROM historique WHERE (idcotation = "
						+ c.getIdCotation() + ") ORDER BY date ASC LIMIT 2";
			}

			/**
			 * @see Feuille-de-suivi, bug n°1
			 * @etat bug connu
			 */
			ResultSet rs2 = ConnecteurBDD.executeQuery(sqlOrder);

			List<Historique> historiques = new ArrayList<Historique>();

			Date d = new Date();

			while (rs2.next()) {

				Historique tempHistorique = new Historique();
				tempHistorique.setIdHistorique(rs2.getInt("idhistorique"));
				tempHistorique.setDate(rs2.getTimestamp("date"));
				tempHistorique.setOuverture(rs2.getFloat("ouverture"));
				tempHistorique.setFermeture(rs2.getFloat("fermeture"));
				tempHistorique.setPlusBas(rs2.getFloat("plusbas"));
				tempHistorique.setPlusHaut(rs2.getFloat("plushaut"));
				tempHistorique.setVolume(rs2.getFloat("volume"));

				historiques.add(tempHistorique);

			}
			Date d2 = new Date();

			c.setHistoriques(historiques);

			// System.out.println(c.getNom() + ", temps DAO pour historique: "
			// + (d2.getTime() - d.getTime()) + "ms");
		}

		return c;
	}

	public Cotation getCotationById(int idcot, boolean getAllHistorique)
			throws SQLException {

		ResultSet rs = ConnecteurBDD.executeQuery("SELECT * FROM cotation WHERE idcotation = " + idcot);

		return getCotation(rs, getAllHistorique);
	}

	public Cotation getCotationByMnemo(String name, boolean getAllHistorique)
			throws SQLException {

		ResultSet rs = ConnecteurBDD.executeQuery(
				"SELECT * FROM cotation WHERE mnemonique LIKE '%" + name
						+ "%' OR mnemonique2 LIKE '%" + name + "%'");

		return getCotation(rs, getAllHistorique);
	}

	public Cotation getCotationByName(String name, boolean getAllHistorique)
			throws SQLException {

		Cotation cotationARecuperer = new Cotation();

		ResultSet rs = ConnecteurBDD.executeQuery("SELECT * FROM cotation c WHERE c.nom = '" + name+ "'");

		return getCotation(rs, getAllHistorique);
	}

	/**
	 * 
	 * @param idCotation
	 * @param range
	 *            , intervalle a récupérer, NULL si tout l'historique est à récupérer
	 * @return
	 * @throws SQLException
	 */
	public List<Historique> getHistorique(int idCotation, Date start, Date end)
			throws SQLException {

		String sqlOrder;

		if (start.equals(null) && end.equals(null)) {
			sqlOrder = "SELECT * FROM historique WHERE idcotation = "
					+ idCotation;
		} else if (end.equals(null)) {
			sqlOrder = "SELECT * FROM historique WHERE idcotation = "
					+ idCotation + " AND date >= '"
					+ Util.getTimeStampByJavaDate(start) + "'";
		} else {
			sqlOrder = "SELECT * FROM historique WHERE idcotation = "
					+ idCotation + " AND date BETWEEN '"
					+ Util.getTimeStampByJavaDate(start) + "' AND '"
					+ Util.getTimeStampByJavaDate(end) + "'";
		}

		ResultSet result = ConnecteurBDD.executeQuery(sqlOrder);

		ArrayList<Historique> histo = new ArrayList<Historique>();
		while (result.next()) {

			Historique tempHistorique = new Historique();

			tempHistorique.setIdHistorique(result.getInt("idhistorique"));
			// tempHistorique.setCotation(c);
			tempHistorique.setDate(result.getTimestamp("date"));
			tempHistorique.setOuverture(result.getFloat("ouverture"));
			tempHistorique.setFermeture(result.getFloat("fermeture"));
			tempHistorique.setPlusBas(result.getFloat("plusbas"));
			tempHistorique.setPlusHaut(result.getFloat("plushaut"));
			tempHistorique.setVolume(result.getFloat("volume"));

			histo.add(tempHistorique);
		}

		return histo;
	}

	public List<Integer> getIdsIndices() throws SQLException {

		ResultSet result = ConnecteurBDD.executeQuery("SELECT DISTINCT IdIndice FROM indice");

		ArrayList<Integer> indices = new ArrayList<Integer>();
		while (result.next()) {
			System.out.println(result.getInt("idindice"));
			indices.add(result.getInt("idindice"));
		}

		return indices;
	}

	/**
	 * Valeurs composant un indice
	 * 
	 * @param idIndice
	 * @return liste des valeurs, triés par leur nom
	 * @throws SQLException
	 */
	public List<Integer> getIndiceComposition(int idIndice) throws SQLException {

		ResultSet result = ConnecteurBDD.executeQuery(
						"SELECT i.idcotation FROM indice i, cotation c WHERE i.idindice = "
								+ idIndice
								+ " AND c.idcotation = i.idcotation ORDER BY c.nom ASC");

		ArrayList<Integer> indices = new ArrayList<Integer>();
		while (result.next()) {
			indices.add(result.getInt("idcotation"));
		}

		return indices;
	}

	public ArrayList<Intraday> getIntraday(int idCotation, Date start)
			throws SQLException {

		ResultSet result;
		String sqlOrder;

		if (start == null) {
			sqlOrder = "SELECT * FROM tempsreel WHERE idcotation = "
					+ idCotation + " AND date >= CURDATE()";
		} else {
			sqlOrder = "SELECT * FROM historique WHERE idcotation = "
					+ idCotation + " AND date >= '"
					+ Util.getTimeStampByJavaDate(start) + "'";
		}

		System.out.println("Intraday : " + sqlOrder);

		result = ConnecteurBDD.executeQuery(sqlOrder);

		ArrayList<Intraday> histo = new ArrayList<Intraday>();
		while (result.next()) {

			Intraday intra = new Intraday();

			intra.setCotation(result.getFloat("cotation"));
			intra.setVolume(result.getLong("volume"));
			intra.setDate(Util.getDateBySQL(result.getTimestamp("date")));

			histo.add(intra);
		}

		return histo;
	}

	public int tailleTableau() {
		return cotation.getHistoriques().size();
	}
}
